1 module hip.filesystem.systems.uwp;
2 import hip.api.filesystem.hipfs;
3 import hip.filesystem.hipfs : HipFile;
4 import hip.error.handler;
5 
6 version(UWP)
7 {
8     import core.sys.windows.windef;
9     import core.sys.windows.winbase;
10     import hip.bind.external : UWPCreateFileFromAppW,
11                         UWPDeleteFileFromAppW,
12                         UWPGetFileAttributesExFromAppW;
13     class HipUWPFile : HipFile
14     {
15         HANDLE fp;
16         import std.utf:toUTF16z;
17         @disable this();
18         this(string path, FileMode mode)
19         {
20             super(path, mode);
21         }
22         bool open(string path, FileMode mode)
23         {
24             DWORD desiredAcces;
25             DWORD shareMode;
26             DWORD createDisposition;
27             switch(mode)
28             {
29                 case FileMode.READ:
30                     desiredAcces = GENERIC_READ;
31                     shareMode = FILE_SHARE_READ;
32                     createDisposition = OPEN_EXISTING;
33                     break;
34                 case FileMode.WRITE:
35                     desiredAcces = GENERIC_WRITE;
36                     shareMode = FILE_SHARE_WRITE;
37                     createDisposition = CREATE_ALWAYS;
38                     break;
39                 case FileMode.READ_WRITE:
40                     desiredAcces = GENERIC_READ | GENERIC_WRITE;
41                     shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
42                     createDisposition = OPEN_ALWAYS;
43                     break;
44                 case FileMode.APPEND:
45                 case FileMode.READ_APPEND:
46                 default:
47                     shareMode = FILE_SHARE_VALID_FLAGS;
48                     desiredAcces = GENERIC_ALL;
49                     createDisposition = OPEN_EXISTING;
50             }
51             
52             fp = UWPCreateFileFromAppW(path.toUTF16z, desiredAcces, shareMode, cast(SECURITY_ATTRIBUTES*)null, createDisposition, 
53             FILE_ATTRIBUTE_NORMAL, cast(void*)null);
54 
55             return fp != null;
56         }
57         int read(void* buffer, ulong count)
58         {
59             if(fp == null) return 0;
60 
61             uint numRead;
62             if(ReadFile(fp, buffer, cast(int)count, &numRead, cast(OVERLAPPED*)null))
63                 return numRead;
64             return 0;
65         }
66         ///Whence is the same from stdio
67         override long seek(long count, int whence)
68         {
69             super.seek(count, whence);
70             if(fp == null) return 0;
71             DWORD winWhence;
72             switch(whence)
73             {
74                 case SEEK_CUR:
75                     winWhence = FILE_CURRENT;
76                     break;
77                 case SEEK_END:
78                     winWhence = FILE_END;
79                     break;
80                 case SEEK_SET:
81                     winWhence = FILE_BEGIN;
82                     break;
83                 default:ErrorHandler.assertExit(false, "Unsupported whence");
84             }
85             LARGE_INTEGER ret;
86             LARGE_INTEGER countTemp;
87             countTemp.QuadPart = count;
88             SetFilePointerEx(fp, countTemp, &ret, winWhence);
89             return cast(int)ret.QuadPart;
90         }
91         ulong getSize()
92         {
93             LARGE_INTEGER lg;
94             if(fp == null) return 0;
95 
96             if(GetFileSizeEx(fp,  &lg))
97                 return cast(ulong)lg.QuadPart;
98             return 0;
99         }
100         void close()
101         {
102             if(fp != null)
103                 CloseHandle(fp);
104         }
105     }
106     class HipUWPileSystemInteraction : IHipFileSystemInteraction
107     {
108         bool read(string path, void delegate(ubyte[] data) onSuccess, void delegate(string err) onError)
109         {
110             if(ErrorHandler.assertLazyErrorMessage(exists(path), "FileSystem Error:", "Filed named '"~path~"' does not exists"))
111                 return false;
112             HipUWPFile f = new HipUWPFile(path, FileMode.READ);
113             import hip.console.log;
114             logln(path, " " , f.getSize);
115             if(f.fp == null || f.getSize == 0)
116             {
117                 onError("Could not acquire file pointer or file has 0 size.");
118                 return false;
119             }
120             ubyte[] output;
121             output.length = f.size;
122             f.read(output.ptr, f.size);
123             f.close();
124             destroy(f);
125             onSuccess(output);
126             return true;
127         }
128         bool write(string path, void[] data)
129         {
130             HipUWPFile f = new HipUWPFile(path, FileMode.WRITE);
131             if(f.fp == null) return false;
132 
133             uint bytesWritten;
134             bool ret = cast(bool)WriteFile(f.fp, data.ptr, cast(uint)data.length, &bytesWritten, cast(OVERLAPPED*)null);
135             destroy(f);
136             return ret;
137         }
138         bool exists(string path)
139         {
140             import std.utf:toUTF16z;
141             WIN32_FILE_ATTRIBUTE_DATA info = void;
142             UWPGetFileAttributesExFromAppW(path.toUTF16z, GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, &info);
143             return info.dwFileAttributes != INVALID_FILE_ATTRIBUTES;
144         }
145         bool remove(string path)
146         {
147             import std.utf:toUTF16z;
148             if(!exists(path)) return false;
149             return cast(bool)DeleteFile(path.toUTF16z);
150         }
151         
152         bool isDir(string path)
153         {
154             return false;
155         }
156         
157     }
158 }